Telegram Group & Telegram Channel
🛠 Создание собственного ResponseWriter: безопасный HTTP в Go

*Автор: Антонио Питаси*
*Источник: [anto.pt](https://anto.pt/articles/go-http-responsewriter)*

📌 Основная идея

В Go интерфейс http.ResponseWriter напрямую записывает данные в сокет, что может приводить к незаметным ошибкам:

• Забывание установки кода состояния ответа.
• Попытка изменить заголовки после начала записи (это не вызовет ошибок, но и не сработает).
• Продолжение выполнения обработчика даже после ошибок, что может повлиять на корректность ответа.

Решение: создать собственную обёртку для ResponseWriter, чтобы добавить проверки и сделать обработку HTTP-запросов более безопасной и предсказуемой.

⚠️ Проблемы стандартного ResponseWriter

1️⃣ Автоматическая установка кода состояния:
Go сам устанавливает код 200 OK при первом вызове Write(), если вы забыли явно вызвать WriteHeader(). Это скрывает ошибки.

2️⃣ Изменение заголовков после начала записи:
После начала отправки тела ответа заголовки нельзя изменить. Go не сигнализирует об этом явно.

3️⃣ Выполнение после ошибок:
Обработчик продолжает выполнение даже после отправки ошибки, если вы забыли поставить return.

## 🧱 Пример реализации обёртки


type HttpWriter struct {
w http.ResponseWriter
headerWritten bool
statusCode int
}

func NewHttpWriter(w http.ResponseWriter) http.ResponseWriter {
return &HttpWriter{w: w}
}

func (w *HttpWriter) Header() http.Header {
return w.w.Header()
}

func (w *HttpWriter) WriteHeader(statusCode int) {
w.w.WriteHeader(statusCode)
w.headerWritten = true
w.statusCode = statusCode
}

func (w *HttpWriter) Write(data []byte) (int, error) {
if !w.headerWritten {
log.Println("⚠️ Предупреждение: Write() вызван без предварительного WriteHeader()")
}
if w.statusCode >= 500 {
log.Println("⚠️ Статус 500: запись игнорируется")
return 0, nil
}
return w.w.Write(data)
}


## 🔄 Интеграция через middleware

Чтобы все обработчики автоматически использовали новый HttpWriter, можно внедрить его через middleware:


func middleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
writer := NewHttpWriter(w)
h.ServeHTTP(writer, r)
})
}


Преимущества

• Явное требование установки кода состояния.
• Логирование попыток записи без WriteHeader().
• Блокировка записи при статусах >=500 для предотвращения некорректного ответа.
• Улучшенная предсказуемость и безопасность обработки HTTP-запросов.

🔗 Подробнее в оригинальной статье



tg-me.com/golang_books/971
Create:
Last Update:

🛠 Создание собственного ResponseWriter: безопасный HTTP в Go

*Автор: Антонио Питаси*
*Источник: [anto.pt](https://anto.pt/articles/go-http-responsewriter)*

📌 Основная идея

В Go интерфейс http.ResponseWriter напрямую записывает данные в сокет, что может приводить к незаметным ошибкам:

• Забывание установки кода состояния ответа.
• Попытка изменить заголовки после начала записи (это не вызовет ошибок, но и не сработает).
• Продолжение выполнения обработчика даже после ошибок, что может повлиять на корректность ответа.

Решение: создать собственную обёртку для ResponseWriter, чтобы добавить проверки и сделать обработку HTTP-запросов более безопасной и предсказуемой.

⚠️ Проблемы стандартного ResponseWriter

1️⃣ Автоматическая установка кода состояния:
Go сам устанавливает код 200 OK при первом вызове Write(), если вы забыли явно вызвать WriteHeader(). Это скрывает ошибки.

2️⃣ Изменение заголовков после начала записи:
После начала отправки тела ответа заголовки нельзя изменить. Go не сигнализирует об этом явно.

3️⃣ Выполнение после ошибок:
Обработчик продолжает выполнение даже после отправки ошибки, если вы забыли поставить return.

## 🧱 Пример реализации обёртки


type HttpWriter struct {
w http.ResponseWriter
headerWritten bool
statusCode int
}

func NewHttpWriter(w http.ResponseWriter) http.ResponseWriter {
return &HttpWriter{w: w}
}

func (w *HttpWriter) Header() http.Header {
return w.w.Header()
}

func (w *HttpWriter) WriteHeader(statusCode int) {
w.w.WriteHeader(statusCode)
w.headerWritten = true
w.statusCode = statusCode
}

func (w *HttpWriter) Write(data []byte) (int, error) {
if !w.headerWritten {
log.Println("⚠️ Предупреждение: Write() вызван без предварительного WriteHeader()")
}
if w.statusCode >= 500 {
log.Println("⚠️ Статус 500: запись игнорируется")
return 0, nil
}
return w.w.Write(data)
}


## 🔄 Интеграция через middleware

Чтобы все обработчики автоматически использовали новый HttpWriter, можно внедрить его через middleware:


func middleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
writer := NewHttpWriter(w)
h.ServeHTTP(writer, r)
})
}


Преимущества

• Явное требование установки кода состояния.
• Логирование попыток записи без WriteHeader().
• Блокировка записи при статусах >=500 для предотвращения некорректного ответа.
• Улучшенная предсказуемость и безопасность обработки HTTP-запросов.

🔗 Подробнее в оригинальной статье

BY Golang Books




Share with your friend now:
tg-me.com/golang_books/971

View MORE
Open in Telegram


Golang Books Telegram | DID YOU KNOW?

Date: |

Telegram announces Anonymous Admins

The cloud-based messaging platform is also adding Anonymous Group Admins feature. As per Telegram, this feature is being introduced for safer protests. As per the Telegram blog post, users can “Toggle Remain Anonymous in Admin rights to enable Batman mode. The anonymized admin will be hidden in the list of group members, and their messages in the chat will be signed with the group name, similar to channel posts.”

A project of our size needs at least a few hundred million dollars per year to keep going,” Mr. Durov wrote in his public channel on Telegram late last year. “While doing that, we will remain independent and stay true to our values, redefining how a tech company should operate.

Golang Books from fr


Telegram Golang Books
FROM USA